/*
 * @Author: WHAlex
 * @Date: 2025-01-17 11:11:12
 *
 * Copyright (c) 2025 by atguigu, All Rights Reserved.
 */
#include "Inf_ES8311.h"

// I2S传输通道声明
static i2s_chan_handle_t speaker_handle;
static i2s_chan_handle_t mic_handle;

// ES8311设备的声明
static esp_codec_dev_handle_t codec_dev;

/**
 * @description: 初始化I2C
 * @return {*}
 */
static void Inf_ES8311_I2C_Init(void)
{
    // I2C配置信息
    i2c_config_t i2c_cfg = {
        .mode = I2C_MODE_MASTER,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = 100000,
    };

    // I2C配置引脚
    i2c_cfg.sda_io_num = SOUND_I2C_SDA_PIN;
    i2c_cfg.scl_io_num = SOUND_I2C_SCL_PIN;

    // I2C配置生效
    i2c_param_config(I2C_NUM_0, &i2c_cfg);

    // 安装I2C驱动
    i2c_driver_install(I2C_NUM_0, i2c_cfg.mode, 0, 0, 0);
}

/**
 * @description: 初始化I2S
 * @return {*}
 */
static void Inf_ES8311_I2S_Init(void)
{
    // I2S操作句柄
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);

    // I2S配置信息(采用标准时序配置)
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(16, I2S_SLOT_MODE_MONO), /* 位深16,单声道 */
        .gpio_cfg = {
            .mclk = SOUND_I2S_MCK_PIN,
            .bclk = SOUND_I2S_BCK_PIN,
            .ws = SOUND_I2S_DATA_WS_PIN,
            .dout = SOUND_I2S_DATA_OUT_PIN,
            .din = SOUND_I2S_DATA_IN_PIN,
        },
    };

    // 创建传输通道
    i2s_new_channel(&chan_cfg, &speaker_handle, &mic_handle);

    // 根据标准模式配置通道
    i2s_channel_init_std_mode(speaker_handle, &std_cfg);
    i2s_channel_init_std_mode(mic_handle, &std_cfg);

    // 使能发送以及接收通道
    i2s_channel_enable(speaker_handle);
    i2s_channel_enable(mic_handle);
}

/**
 * @description: 初始化ES8311设备
 * @return {*}
 */
static void Inf_ES8311_DEV_Init(void)
{
    // I2S配置
    audio_codec_i2s_cfg_t i2s_cfg = {
        .port = I2S_NUM_0,
        .tx_handle = speaker_handle,
        .rx_handle = mic_handle,
    };

    // 根据I2S配置创建数据接口(收发音频数据)
    const audio_codec_data_if_t *data_if = audio_codec_new_i2s_data(&i2s_cfg);

    // I2C配置信息
    audio_codec_i2c_cfg_t i2c_cfg = {
        .addr = ES8311_CODEC_DEFAULT_ADDR,
        .port = I2C_NUM_0,
        //.bus_handle = &i2c_bus_handle, // 不需要配置,使用新I2C API需要配置
    };

    // 根据I2C配置创建控制接口(用于向ES8311设备寄存器写值)
    const audio_codec_ctrl_if_t *out_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg);

    // 配置引脚接口
    const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio();

    // ES8311设备配置信息
    es8311_codec_cfg_t es8311_cfg = {
        .codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH,
        .ctrl_if = out_ctrl_if,
        .gpio_if = gpio_if,
        .pa_pin = SOUND_PA_PIN,
        .use_mclk = true,
        .digital_mic = false, // 数字Mic
        .pa_reverted = false,
    };

    // 根据设备配置信息创建设备接口
    const audio_codec_if_t *out_codec_if = es8311_codec_new(&es8311_cfg);

    // 设备配置信息
    esp_codec_dev_cfg_t dev_cfg = {
        .codec_if = out_codec_if,
        .data_if = data_if,
        .dev_type = ESP_CODEC_DEV_TYPE_IN_OUT,
    };

    // 创建设备
    codec_dev = esp_codec_dev_new(&dev_cfg);

    // 配置输出音量
    esp_codec_dev_set_out_vol(codec_dev, 60);

    // 配置输入增益
    esp_codec_dev_set_in_gain(codec_dev, 30);

    // 采样配置信息
    esp_codec_dev_sample_info_t fs = {
        .sample_rate = 16000, // 采样率
        .channel = 1,         // 转换通道数
        .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0),
        .bits_per_sample = 16, // 位深
        .mclk_multiple = 256,
    };

    // 启动设备
    esp_codec_dev_open(codec_dev, &fs);
}

/**
 * @description: 初始化音频模块
 * @return {*}
 */
void Inf_ES8311_Init(void)
{
    /* 1.初始化I2C */
    Inf_ES8311_I2C_Init();

    /* 2.初始化I2S */
    Inf_ES8311_I2S_Init();

    /* 3.初始化编解码器(ES8311)设备 */
    Inf_ES8311_DEV_Init();
}

/**
 * @description: 向音频模块(ES8311)写数据
 * @return {*}
 */
esp_err_t Inf_ES8311_WriteData(char *data, size_t len)
{
    // if (codec_dev != NULL && data != NULL && len > 0)
    // {
    return esp_codec_dev_write(codec_dev, data, len);
    // }
}

/**
 * @description: 从音频模块(ES8311)读数据
 * @return {*}
 */
esp_err_t Inf_ES8311_ReadData(uint8_t data[], size_t len)
{
    // if (codec_dev != NULL)
    // {
    return esp_codec_dev_read(codec_dev, data, len);
    // }
}